home *** CD-ROM | disk | FTP | other *** search
- /* Listing 16.21 Light shader simulating sunlight through a window*/
- /*
- * windowlight(): Cast patches of light as through a paned window.
- */
- light
- RCWindowLight(
- point from = point "world" ( 0, 0, -20),
- to = point "world" (0, 0, 0),
- center = point "world" (0, 0, -4),
- in = point "world" (0, 0, 1),
- up = point "world" (0, 1, 0);
- color lightcolor = color (1, .9, .6),
- darkcolor = color (.05, .2, .1);
- float intensity = 1,
- xorder = 2, /* number of panes horizontally */
- yorder = 3, /* number of panes vertically */
- panewidth = 6, /* horizontal size of a pane */
- paneheight = 6, /* vertical size of a pane */
- framewidth = 1, /* sash width between panes */
- fuzz = .2;) /* transition region between pane and sash */
- {
- uniform
- point in2, /* normalized in */
- right, /* unit vector perpendicular to in2 and up2 */
- up2, /* normalized up perpendicular to in */
- corner, /* location of lower left corner of window */
- path; /* direction of sunlight travel */
- point PtoC, /* vector from surface point to window corner */
- PtoF; /* vector from surface point to wall along path */
- float offset, modulus, yfract, xfract;
-
- /* Initialize the uniform variables */
- path = (from - to);
- in2 = normalize(in);
- in2 *= sign(-path.in2);
- right = up ^ in2;
- up2 = normalize(in2 ^ right);
- right = up2 ^ in2;
- corner = center - right*xorder*panewidth/2 -
- up2*yorder*paneheight/2;
-
- solar( -path, 0.0 ) {
-
- PtoC = corner - Ps;
- if (path.PtoC <= 0) { /* outdoors => full illumination */
- xfract = yfract = 1;
- } else {
-
- /*
- * Make PtoF be a vector from the surface point to the wall
- * by adjusting the length of the reflected vector path.
- */
- PtoF = path * (PtoC.in2)/(path.in2);
-
- /*
- * Calculate the vector from the corner to the intersection point, and
- * project it onto up2. This length is the vertical offset of the
- * intersection point within the window.
- */
- offset = (PtoF - PtoC).up2;
- modulus = mod(offset, paneheight);
- if( offset > 0 && offset/paneheight < yorder ) { /* inside window */
- if( modulus > (paneheight/2))
- modulus = paneheight - modulus; /* symmetry in pane */
- yfract = smoothstep( /* include sash fuzz */
- (framewidth/2) - (fuzz/2),
- (framewidth/2) + (fuzz/2),
- modulus);
- } else {
- yfract = 0;
- }
-
- /* Repeat for horizontal offset */
- offset = (PtoF - PtoC).right;
- modulus = mod(offset, panewidth);
- if( offset > 0 && offset/panewidth < xorder ) {
- if( modulus > (panewidth/2))
- modulus = panewidth - modulus;
- xfract = smoothstep(
- (framewidth/2) - (fuzz/2),
- (framewidth/2) + (fuzz/2),
- modulus);
- } else {
- xfract = 0;
- }
- }
- Cl = intensity * mix( darkcolor, lightcolor, yfract*xfract);
- }
- }
-